package com.xbongbong.paas.service.stage.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EnableEnum;
import com.xbongbong.paas.enums.StageSettingEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.model.StageProcessModel;
import com.xbongbong.paas.pojo.StageListPojo;
import com.xbongbong.paas.pojo.StageSavePojo;
import com.xbongbong.paas.pojo.vo.StageGetVO;
import com.xbongbong.paas.service.stage.AbstractStageHandleImpl;
import com.xbongbong.paas.service.stage.StageHandle;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.script.pojo.dto.StageSettingScriptDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.SaleStageEntity;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.model.SaleStageModel;
import org.apache.commons.collections4.MapUtils;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 机会阶段策略
 * @author 李少杰
 * @version v1.0.0
 * @date 2021/11/22 19:46
 */
@Service("opportunityStageHandle")
public class OpportunityStageHandle extends AbstractStageHandleImpl implements StageHandle {

    private static final Logger LOG = LoggerFactory.getLogger(OpportunityStageHandle.class);
    @Resource
    private SaleStageModel saleStageModel;
    @Resource
    private StageProcessModel stageProcessModel;


    @Override
    public Integer businessType() {
        return XbbRefTypeEnum.SALES_OPPORTUNITY.getCode();
    }

    @Override
    public PaasStageEntity getByKey(Long stageId, String corpid) throws XbbException {
        return saleStageModel.getByKey(stageId, corpid);
    }

    @Override
    public List<PaasStageEntity> findEntitys(Map<String, Object> params) {
        List<SaleStageEntity> entitys = saleStageModel.findEntitys(params);
        return new ArrayList<>(Arrays.asList(entitys.toArray(new PaasStageEntity[0])));
    }

    @Override
    public Integer insert(PaasStageEntity entity) throws XbbException {
        entity.setUpdateTime(DateTimeUtil.getInt());
        entity.setAddTime(DateTimeUtil.getInt());
        return saleStageModel.insert((SaleStageEntity) entity);
    }

    @Override
    public Integer update(PaasStageEntity entity) throws XbbException {
        entity.setUpdateTime(DateTimeUtil.getInt());
        return saleStageModel.update((SaleStageEntity) entity);
    }

    @Override
    public Integer getEntitysCount(Map<String, Object> param) {
        return saleStageModel.getEntitysCount(param);
    }

    @Override
    public Integer deleteBatch(List<PaasStageEntity> paasStageEntityList, String corpid) {
        return saleStageModel.deleteBatch(beanTransform4List(paasStageEntityList), corpid);
    }

    @Override
    public void insertBatch(List<PaasStageEntity> list) {
        list.forEach(item -> {
            item.setAddTime(DateTimeUtil.getInt());
            item.setUpdateTime(DateTimeUtil.getInt());
        });
        saleStageModel.insertBatch(beanTransform4List(list));
    }

    @Override
    public void insertBatch4Script(List<PaasStageEntity> list) {
        list.forEach(item -> {
            item.setAddTime(DateTimeUtil.getInt());
            item.setUpdateTime(DateTimeUtil.getInt());
        });
        saleStageModel.insertBatch4Script(beanTransform4List(list));
    }

    @Override
    public void updateBatch(List<PaasStageEntity> list, String corpid) {
        list.forEach(item -> item.setUpdateTime(DateTimeUtil.getInt()));
        saleStageModel.updateBatch(beanTransform4List(list), corpid);
    }

    @Override
    public void updateBatchDefaultAndLinkOption(List<PaasStageEntity> list, String corpid) {
        list.forEach(item -> item.setUpdateTime(DateTimeUtil.getInt()));
        saleStageModel.updateBatchDefaultAndLinkOption(beanTransform4List(list), corpid);
    }

    @Override
    public void updateBatch4MirrorRollback(List<PaasStageEntity> list, String corpid) {
        saleStageModel.updateBatch4MirrorRollback(beanTransform4List(list), corpid);
    }

    @Override
    public void updateBatch4Script(List<PaasStageEntity> list) {
        saleStageModel.updateBatch4Script(beanTransform4List(list));
    }

    @Override
    public PaasStageEntity getByCode(String corpid, Long formId, String stageCode) {
        return saleStageModel.getByCode(corpid, formId, stageCode);
    }

    @Override
    public List<ItemPoJo> getStageByStageProgress(Map<String, Object> params, Long formId, String corpid) throws XbbException {
        List<SaleStageEntity> saleStageModelEntitys = saleStageModel.findEntitys(params);
        if (CollectionsUtil.isEmpty(saleStageModelEntitys)){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return updateStageInfoInExplain(saleStageModelEntitys, formId, corpid);

    }

    @Override
    public void updateStageDefaultAndOption(List<FieldAttrEntity> explains, Long formId, String corpid) throws XbbException {
        List<SaleStageEntity> updateSaleStageEntities = new ArrayList<>();
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        try {
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(JSONArray.toJSONString(explains));
            FieldAttrEntity fieldAttrEntity = explainMap.get(SalesOpportunityEnum.SALE_STAGE.getAttr());
            if (Objects.isNull(fieldAttrEntity)) {
                return;
            }
            List<ItemPoJo> itemPojos = fieldAttrEntity.getItems();
            if (CollectionsUtil.isEmpty(itemPojos)) {
                return;
            }
            Long stageProcessId;
            if (Objects.equals(fieldAttrEntity.getStageMultiVersion(), 1)) {
                // 开启多版本启用的时候，表单设计页显示的阶段是默认版本的阶段
                stageProcessId = fieldAttrEntity.getDefaultStageProcessId();
                if (Objects.isNull(stageProcessId)) {
                    return;
                }
            } else {
                // 单版本启用的时候，表单设计页显示的阶段是当前启用版本的阶段
                StageProcessEntity stageProcessEntity = stageProcessModel.getEnableStageProcess(corpid, formId);
                if (Objects.isNull(stageProcessEntity)) {
                    return;
                }
                stageProcessId = stageProcessEntity.getId();
            }
            params.put(ParameterConstant.CORPID, corpid);
            params.put(ParameterConstant.FORMID, formId);
            params.put(ParameterConstant.DEL, BasicConstant.ZERO);
            params.put(ParameterConstant.ENABLE, BasicConstant.ONE);
            params.put(ParameterConstant.STAGE_PROCESS_ID, stageProcessId);
            params.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT + " " + SortOrder.DESC);
            List<SaleStageEntity> saleStageEntities = saleStageModel.findEntitys(params);
            Map<String, SaleStageEntity> saleStageEntityMap = saleStageEntities.stream().collect(Collectors.toMap(SaleStageEntity::getCode, Function.identity()));
            for (ItemPoJo item : itemPojos) {
                SaleStageEntity saleStageEntity = saleStageEntityMap.get(String.valueOf(item.getValue()));
                if (Objects.equals(item.getChecked(),true)) {
                    saleStageEntity.setIsDefault(BasicConstant.ONE);
                } else {
                    saleStageEntity.setIsDefault(BasicConstant.ZERO);
                }
                if (Objects.nonNull(item.getFieldMap())) {
                    saleStageEntity.setLinkOption(JSONArray.parseArray(JSON.toJSONString(item.getFieldMap())));
                } else {
                    saleStageEntity.setLinkOption(null);
                }
                saleStageEntity.setUpdateTime(DateTimeUtil.getInt());
                updateSaleStageEntities.add(saleStageEntity);
            }
            saleStageModel.updateBatch(updateSaleStageEntities, corpid);
        } catch (Exception e) {
            LOG.error("OpportunityStageHandle.updateStageDefaultAndOption 出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * TODO 先强转，数据迁移后移除次方法
     * @param paasStageEntityList
     * @return
     */
    private List<SaleStageEntity> beanTransform4List(List<PaasStageEntity> paasStageEntityList) {
        return (List<SaleStageEntity>)(Object)paasStageEntityList;
    }

    @Override
    public void stageGetSettingAdvance(PaasStageEntity paasStageEntity, Object stageVO, Integer stageSetting) {
        if (Objects.nonNull(paasStageEntity) && Objects.nonNull(stageVO)) {
            try {
                SaleStageEntity saleStageEntity = (SaleStageEntity) paasStageEntity;
                if (Objects.equals(StageTypeEnum.SUCCESS_STAGE.getType(), paasStageEntity.getType())) {
                    // 是否允许新建合同，阶段自动跳转此阶段
                    StageSettingEnum stageSettingEnum = StageSettingEnum.getByCode(stageSetting);

                    switch (stageSettingEnum) {
                        case NEXT_STEP_STAGE_DETAIL:
                            StageGetVO stageGetVO = (StageGetVO) stageVO;
                            stageGetVO.setAllowCreateContractSkipStage(saleStageEntity.getAllowCreateContractSkipStage());
                            break;
                        case MAIN:
                        case MAIN_CLICK_NEXT_STEP:
                            StageListPojo stageListPojo = (StageListPojo) stageVO;
                            stageListPojo.setAllowCreateContractSkipStage(saleStageEntity.getAllowCreateContractSkipStage());
                            break;
                        default:
                    }

                }
            } catch (Exception e) {
                LOG.error("OpportunityStageHandle.stageGetSettingAdvance", e);
            }
        }
    }

    @Override
    public void stageSaveSettingAdvance(PaasStageEntity paasStageEntity, Object stageSave, Integer stageSetting) {
        if (Objects.nonNull(paasStageEntity) && Objects.nonNull(stageSave)) {
            try {
                StageSettingEnum stageSettingEnum = StageSettingEnum.getByCode(stageSetting);
                switch (stageSettingEnum) {
                    case NEXT_STEP_STAGE_DETAIL:
                    case MAIN_SAVE:
                    case MAIN_COPY:
                        StageSavePojo stageSavePojo = (StageSavePojo) stageSave;
                        if (Objects.equals(stageSavePojo.getType(), StageTypeEnum.SUCCESS_STAGE.getType())) {
                            // 是否允许新建合同，阶段自动跳转此阶段
                            Integer allowCreateContractSkipStage = Objects.isNull(stageSavePojo.getAllowCreateContractSkipStage()) ? EnableEnum.OPEN.getCode() : stageSavePojo.getAllowCreateContractSkipStage();
                            paasStageEntity.setAllowCreateContractSkipStage(allowCreateContractSkipStage);
                        }
                        break;
                    default:
                }
            } catch (Exception e) {
                LOG.error("OpportunityStageHandle.stageSaveSettingAdvance", e);
            }
        }
    }
}
